Skip to content

Comments

Add rowId to provisioned dataclass table#7439

Open
XingY wants to merge 8 commits intodevelopfrom
fb_sourceRowId
Open

Add rowId to provisioned dataclass table#7439
XingY wants to merge 8 commits intodevelopfrom
fb_sourceRowId

Conversation

@XingY
Copy link
Contributor

@XingY XingY commented Feb 20, 2026

Rationale

In preparation for work to consolidate dataclass update methods (from the current single _update vs DIB based batch update), we need to make some changes to the current dataclass schema.

  1. provisioned currently has lsid, but not rowId. The plan is to support update using rowId as key only. This requires rowId to be available on provisioned table.
  2. there is a classid on provisioned, which provides no value since it's static. This should be removed.

This PR does not drop LSID from provisioned, nor does it deprecate support of update using LSID.

Related Pull Requests

Changes

  • drop classId from provisioned dataclass table since it's not needed
  • add rowId to provisioned dataclass table
  • migration script to handle dataclass domain field, indexes updates
  • switch exp.data to join on rowId instead of lsid, in preparation of dropping provisioned.lsid in the future
  • always reselectId for dataclass during insert/merge. This likely won't have much perf impact since we are already doing it when audit is turned on, which is the default behavior.

This comment was marked as resolved.

@XingY XingY requested a review from labkey-nicka February 23, 2026 18:41
let fieldName = generateFieldName(length, charset);
while (!canNameBeUsedInImport(fieldName))
{
fieldName = generateFieldName();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be passed length and charset as well?

Set<String> dataCols = new CaseInsensitiveHashSet(_rootTable.getColumnNameSet());

// all columns from dataclass property table except name, lsid, and classid
// all columns from dataclass property table except name, lsid
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Consider changing this comment so it does not also need to enumerate what is changing. Something like:

// All columns from dataclass property table except key columns

// pass
}
if (null == kind || null == kind.getStorageSchemaName())
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log a message here stating that the kind or storage schema could not be resolved before returning.

* Drop the classid column and add a rowId column to existing provisioned DataClass tables.
*/
@SuppressWarnings("unused")
@DeferredUpgrade
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, does this script need to be deferred?

// Set NOT NULL constraint
SqlExecutor executor = new SqlExecutor(scope);
boolean isPostgreSQL = scope.getSqlDialect().isPostgreSQL();
if (isPostgreSQL)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Consider using the table for these statements:

// Set NOT NULL constraint
SqlExecutor executor = new SqlExecutor(scope);
if (scope.getSqlDialect().isPostgreSQL())
    executor.execute(new SQLFragment("ALTER TABLE ").append(provisionedTable).append(" ALTER COLUMN rowId SET NOT NULL"));
else
    executor.execute(new SQLFragment("ALTER TABLE ").append(provisionedTable).append(" ALTER COLUMN rowId INT NOT NULL"));

Same for the FK constraint call.

// update description and fieldName value from Import with update, the import columns contains name field, verify update is successful and data are updated correctly
const importUpdateText = 'Name\tDescription\t' + fieldName + '\n' + newName3 + '\timportUpd1\timportVal1\n' + newName4 + '\timportUpd2\timportVal2';
const updateResp = await ExperimentCRUDUtils.importData(server, importUpdateText, dataType, 'UPDATE', topFolderOptions, editorUserOptions);
expect(updateResp.text.indexOf('"success" : true') > -1).toBeTruthy();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Consider using the response body instead.

expect(updateResp.body.success).toBe(true);

Same for the mergeResp below.

// insert 2 rows data, provide explicit names and a rowId = 1
const dataName1 = 'KeyData1';
const dataName2 = 'KeyData2';
const inserted = await insertDataClassData([
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This could be flaky if this is the first test run on a new database (as it was for me locally 😄). Consider using -1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants